package com.star.mall.file.impl;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import com.star.mall.base.exception.BusinessException;
import com.star.mall.file.FileService;
import com.star.mall.file.model.IFile;
import com.star.mall.utils.UniqueIdUtil;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.PutObjectOptions;
import io.minio.errors.InvalidEndpointException;
import io.minio.errors.InvalidPortException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.io.OutputStream;

@Service("minio")
@Slf4j
@ConditionalOnProperty(
        prefix = "system.file",
        name = {"mode"},
        havingValue = "minio",
        matchIfMissing = true
)
public class MinioFileService implements FileService {

    @Value("${system.file.endpoint}")
    private String endpoint;
    @Value("${system.file.accessKeyId}")
    private String accessKeyId;
    @Value("${system.file.accessKeySecret}")
    private String accessKeySecret;
    @Value("${system.file.bucketName}")
    private String bucketName;

    private MinioClient initClient() throws InvalidPortException, InvalidEndpointException {
        return new MinioClient(endpoint, accessKeyId, accessKeySecret);
    }

    @Override
    public void uploadFile(IFile file, InputStream inputStream) {
        String key = UniqueIdUtil.getSid();
        file.setKey(key);
        saveFile(inputStream, bucketName, key);
        file.setPath(bucketName);
    }

    @Override
    public void saveFile(InputStream inputStream, String resourceLocation, String fileName) {
        try {
            MinioClient client = initClient();
            if (!client.bucketExists(resourceLocation)) {
                client.makeBucket(resourceLocation);
            }
            client.putObject(resourceLocation, fileName, inputStream, new PutObjectOptions(-1, PutObjectOptions.MIN_MULTIPART_SIZE));
        }catch (Exception e) {
            log.error("上传文件失败：{}", ExceptionUtil.stacktraceToString(e));
            throw new BusinessException("上传文件失败");
        }
    }

    @Override
    public void downloadFile(String resourceLocation, String fileName, OutputStream outputStream) {
        try {
            MinioClient client = initClient();
            InputStream inputStream = client.getObject(resourceLocation, getFileName(fileName));
            IoUtil.copy(inputStream, outputStream);
        }catch(Exception e) {
            log.error("下载文件失败：{}", ExceptionUtil.stacktraceToString(e));
            throw new BusinessException("下载文件失败");
        }
    }

    private String getFileName(String fileName) {
        return fileName.replace("."+FileUtil.extName(fileName), "");
    }

    @Override
    public boolean deleteFile(String resourceLocation, String fileName) {
        try {
            String file = getFileName(fileName);
            MinioClient client = initClient();
            ObjectStat objectStat = client.statObject(resourceLocation, getFileName(file));
            if (objectStat != null) {
                client.removeObject(resourceLocation, file);
                return true;
            }
        }catch (Exception e) {
            log.error("删除文件失败：{}", ExceptionUtil.stacktraceToString(e));
            throw new BusinessException("删除文件失败");
        }
        return false;
    }
}
